#define _GNU_SOURCE
#include "app_bt.h"
#include "log/log.h"
#include <string.h>
#include <unistd.h>
#include "app_serial.h"

static char read_buf[1024];               // 用来缓存多个蓝牙数据包
static int buf_len = 0;                   // 缓存数据的长度
static char fix_header[2] = {0xf1, 0xdd}; // 蓝牙数据固定的头部


static int init_bt(Device *device)
{
    // 初始化串口 9600 阻塞
    app_serial_init(device);

    app_serial_setBlock(device, 0);  // 初始时为非阻塞模式
    tcflush(device->fd,TCIOFLUSH );           // 清空串口缓存
    //判断蓝牙是否可用
    if (app_bt_status(device) == 0)
    {
        // 修改蓝牙属性
        app_bt_rename(device, "123456");
        app_bt_setBaudRate(device, BT_115200);
        

        // 重置
        app_bt_reset(device);
        sleep(2); // 等待蓝牙重启
    }

    // 将串口的波特率修改为115200
    app_serial_setBraudRate(device, BR_115200);
    tcflush(device->fd, TCIOFLUSH);

    app_bt_setNetId(device, "8002"); // 设置蓝牙网络ID
    app_bt_setMAddr(device, "0001"); // 设置蓝牙主地址
    // 判断蓝牙是否可用 不可用返回-1
    if (app_bt_status(device) != 0)
    {
        log_debug("蓝牙初始化失败");
        return -1;
    }
    

    // 将串口改为阻塞模式
    app_serial_setBlock(device, 1);
    tcflush(device->fd, TCIOFLUSH);

    log_debug("蓝牙初始化成功");
    return 0;
}

/**
 * 初始化
 */
int app_bt_init(Device *device)
{
    // 将蓝牙数据读后处理函数和写前处理函数注册到设备中
    device->pre_write = app_bt_preWrite;
    device->post_read = app_bt_postRead;

    // 初始化蓝牙
    return init_bt(device);
}



static void remove_data(int len)
{
    memmove(read_buf, read_buf + len, buf_len - len);
    buf_len -= len;
}

/**
 * 蓝牙数据的读后处理
 * 接收方得到数据1（4）：ok\r\n
接收方得到数据2（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间）
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据
处理后的数据格式：conn_type id_len msg_len id msg

    data很可能不是一个完整的蓝牙数据包，需要将多个data拼接起来，然后找出一个完整的蓝牙数据包
 */
int app_bt_postRead(char *data, int len)
{
    log_debug("收到的蓝牙数据：%.*s", len, data);
    memcpy(read_buf + buf_len, data, len);
    buf_len += len;
    // 如果缓存数据长度小于8，说明不是一个完整的蓝牙数据包，返回
    if (buf_len < 8)
    {
        return 0;
    }
    int i = 0;
    for ( i = 0; i < buf_len - 7; i++)
    {
        // 找到蓝牙数据包的头部
        if (memcmp(read_buf + i, fix_header, 2) == 0)
        {
            if(i > 0)
            {
                remove_data(i); // 移除缓存数据中无效的数据
            }
            // 判断蓝牙数据是否完整
            if (buf_len < read_buf[2] + 3)
            {
                log_debug("蓝牙数据不完整");
                return 0;
            }
            // 蓝牙数据完整，处理数据
            memset(data, 0, len);
            data[0] = 1; // conn_type   
            data[1] = 2; // id_len
            data[2] = read_buf[2] - 4; // msg_len
            memcpy(data + 3, read_buf + 3, 2);  // id
            memcpy(data + 5, read_buf + 7, read_buf[2]);  // msg

            // 移除已经复制的蓝牙缓存数据
            remove_data(read_buf[2] + 3);

            return 3 + 2 + data[2];
        }   
    }
    remove_data(i); // 移除缓存数据中无效的数据

    return 0;
}

/**
 * 蓝牙数据的写前处理
 * 字符数组消息: 
    例子：1 2 3 XX abc
    格式：conn_type id_len msg_len id msg
蓝牙发送数据格式例子：
    例子：41 54 2b 4d 45 53 48 00 ff ff 61 62 63 0d 0a
    41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
    ff ff: 对端的MADDR（如果是FFFF代表群发）
    61 62 63: 要发送的数据（不超过12字节）
    0d 0a：\r\n（固定结尾）
 */
int app_bt_preWrite(char *data, int len)
{
    if( len < 6 )
    {
        return 0;
    }
    //计算数据长度
    int buf_len = 12 + data[2]; // 12:固定长度  data[2]:msg_len
    char buf[buf_len];

    // 拼接AT指令
    memcpy(buf, "AT+MESH", 8);
    memcpy(buf + 8, data + 3, 2); // id
    memcpy(buf + 10, data + 5, data[2]); // msg
    memcpy(buf + 10 + data[2], "\r\n", 2); // 结尾

    memset(data, 0, len);
    memcpy(data, buf, buf_len);

    log_debug("生成的蓝牙数据: %.*s",buf_len, data);
    
    return buf_len;

}

static int wait_Ack(Device *device)
{
    usleep(50 * 1000);
    // 等待蓝牙返回数据
    char buf[4];
    read(device->fd, buf, sizeof(buf));
    if( memcmp(buf, "OK\r\n", 4) == 0 )
    {
        return 0;
    }
    return -1;
}

/**
 *  测试蓝牙是否可用
 */
int app_bt_status(Device *device)
{
    // 向串口发送AT指令
    write(device->fd,"AT\r\n", 4);
    return wait_Ack(device);
}

/**
 *  修改蓝牙名称
 */
int app_bt_rename(Device *device, char *name)
{
    // 向串口发送AT指令
    char buf[100];
    sprintf(buf, "AT+NAME%s\r\n", name);
    write(device->fd, buf, strlen(buf));
    return wait_Ack(device);
}

/**
 *  修改蓝牙波特率
 */
int app_bt_setBaudRate(Device *device, BTBraudRate baud_rate)
{
    // 向串口发送AT指令
    char buf[100];
    sprintf(buf, "AT+BAUD%c\r\n", baud_rate);
    write(device->fd, buf, strlen(buf));
    return wait_Ack(device);
}

/**
 *  启动蓝牙
 */
int app_bt_reset(Device *device)
{
    // 向串口发送AT指令
    write(device->fd, "AT+RESET\r\n", 10);
    return wait_Ack(device);
}

/**
 *  设置组网id
 */
int app_bt_setNetId(Device *device, char *net_id)
{
    // 向串口发送AT指令
    char buf[100];
    sprintf(buf, "AT+NETID%s\r\n", net_id);
    write(device->fd, buf, strlen(buf));
    return wait_Ack(device);
}

/**
 *  设置MAC地址
 */
int app_bt_setMAddr(Device *device, char *maddr)
{
    // 向串口发送AT指令
    char buf[100];
    sprintf(buf, "AT+MADDR%s\r\n", maddr);  
    write(device->fd, buf, strlen(buf));
    return wait_Ack(device);
}
